// today_main.js — Home/Today page logic (redesigned)
// Compact, no-scroll layout: inline stats + rank, 2-column (Posts | Messages), progress bar

let briefingData = null;
let rankData = null;

const MAX_MESSAGES = 5; // Show top N messages, rest behind "View all"

async function loadBriefing() {
    try {
        // Fetch briefing + rank in parallel
        const [briefResp, rankResp] = await Promise.all([
            fetch('/api/today/briefing'),
            fetch('/api/community/rank').catch(() => null)
        ]);

        if (!briefResp.ok) throw new Error('Failed to load briefing: HTTP ' + briefResp.status);
        briefingData = await briefResp.json();

        if (rankResp && rankResp.ok) {
            rankData = await rankResp.json();
        }

        document.getElementById('todayDate').textContent = formatBriefingDate(briefingData.date);
        renderStatsBar(briefingData.headline, rankData);

        const container = document.getElementById('todayColumns');
        container.innerHTML = '';
        container.innerHTML += renderPostSuggestionsSection(briefingData);
        container.innerHTML += renderMessagesSection(briefingData);

        // Async loads (don't block initial render)
        loadOutreachData();
        loadContentPlan();
    } catch (e) {
        console.error('[Today] Error loading briefing:', e);
        const container = document.getElementById('todayColumns');
        container.innerHTML = `<div class="today-section">
            <div class="today-section__empty">Failed to load briefing. <button class="ck-btn ck-btn--secondary ck-btn--xs" onclick="loadBriefing()">Retry</button></div>
        </div>`;
    }
}

function formatBriefingDate(dateStr) {
    if (!dateStr) return '';
    try {
        const d = new Date(dateStr + 'T00:00:00');
        return d.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
    } catch {
        return dateStr;
    }
}

// =============================================================================
// Stats Bar — compact inline stats + rank chip
// =============================================================================

function renderStatsBar(h, rank) {
    if (!h) return;
    const el = document.getElementById('statsBar');

    const atRisk = (h.at_risk_count || 0) + (h.critical_count || 0);
    const warnCls = atRisk > 0 ? ' today-stat--warning' : '';

    const atRiskPct = h.total_members > 0 ? Math.round((atRisk / h.total_members) * 100) : 0;

    const atRiskDelta = h.at_risk_delta || 0;
    const activeDelta = h.active_members_week_delta || 0;
    const activitiesWeek = h.activities_week || 0;
    const activitiesWeekDelta = h.activities_week_delta || 0;

    let html = `
        <div class="today-stat">
            <span class="today-stat__info"><span class="ck-help-icon">?<span class="ck-help-tip">Total unique members synced from your Skool community. Delta shows new members who joined since Monday.</span></span></span>
            <div class="today-stat__center">
                <span class="today-stat__value">${h.total_members.toLocaleString()}</span>
                <span class="today-stat__label">Members</span>
                ${renderDelta(h.new_members_week, '+', ' this week')}
            </div>
        </div>
        <div class="today-stat${warnCls}">
            <span class="today-stat__info"><span class="ck-help-icon">?<span class="ck-help-tip">Members with a churn score above 50 (at-risk + critical). Delta compares to last Monday's snapshot.</span></span></span>
            <div class="today-stat__center">
                <span class="today-stat__value">${atRisk.toLocaleString()}</span>
                <span class="today-stat__label">At risk (${atRiskPct}%)</span>
                ${renderDelta(atRiskDelta, '+', ' vs last week', true)}
            </div>
        </div>
        <div class="today-stat">
            <span class="today-stat__info"><span class="ck-help-icon">?<span class="ck-help-tip">Members who posted or commented since Monday. Delta compares to the same days last week (e.g. on Wednesday: this Mon–Wed vs last Mon–Wed).</span></span></span>
            <div class="today-stat__center">
                <span class="today-stat__value">${h.active_members_week.toLocaleString()}</span>
                <span class="today-stat__label">Active</span>
                ${renderDelta(activeDelta, '+', ' vs last week')}
            </div>
        </div>
        ${activitiesWeek > 0 ? `<div class="today-stat">
            <span class="today-stat__info"><span class="ck-help-icon">?<span class="ck-help-tip">Total community activities since Monday from Skool admin metrics. Delta compares to the same days last week (e.g. on Wednesday: this Mon–Wed vs last Mon–Wed).</span></span></span>
            <div class="today-stat__center">
                <span class="today-stat__value">${activitiesWeek.toLocaleString()}</span>
                <span class="today-stat__label">Activities</span>
                ${renderDelta(activitiesWeekDelta, '+', ' vs last week')}
            </div>
        </div>` : ''}
    `;

    // Rank chip with deltas (right-aligned)
    if (rank && rank.current) {
        const c = rank.current;
        const b = rank.baseline;
        let rankDeltaHtml = '';
        let catDeltaHtml = '';
        if (b && b.recorded_at !== c.recorded_at) {
            const rankDiff = b.rank - c.rank;
            const catDiff = b.category_rank - c.category_rank;
            if (rankDiff !== 0) {
                const rCls = rankDiff > 0 ? 'today-stat__delta--up' : 'today-stat__delta--down';
                const rArrow = rankDiff > 0 ? '\u2191' : '\u2193';
                rankDeltaHtml = `<div class="today-stat__delta ${rCls}">${rArrow}${Math.abs(rankDiff)}</div>`;
            }
            if (catDiff !== 0) {
                const cCls = catDiff > 0 ? 'today-stat__delta--up' : 'today-stat__delta--down';
                const cArrow = catDiff > 0 ? '\u2191' : '\u2193';
                catDeltaHtml = `<div class="today-stat__delta ${cCls}">${cArrow}${Math.abs(catDiff)}</div>`;
            }
        }
        html += `
            <div class="today-rank">
                <div class="today-rank__item">
                    <div class="today-rank__value">#${c.rank.toLocaleString()}</div>
                    <div class="today-rank__label">Overall <span class="ck-help-icon">?<span class="ck-help-tip">Your community's overall Skool discovery rank. Lower is better. Delta since first tracked snapshot.</span></span></div>
                    ${rankDeltaHtml}
                </div>
                <div class="today-rank__divider"></div>
                <div class="today-rank__item">
                    <div class="today-rank__value">#${c.category_rank}</div>
                    <div class="today-rank__label">${escHtml(c.category_name || 'Category')} <span class="ck-help-icon">?<span class="ck-help-tip">Your rank within the "${escHtml(c.category_name || 'Category')}" category on Skool. Delta since first tracked snapshot.</span></span></div>
                    ${catDeltaHtml}
                </div>
            </div>
        `;
    }

    el.innerHTML = html;
}

function renderDelta(value, prefix, suffix, invertColors) {
    if (value == null) return '';
    if (value === 0) {
        return `<div class="today-stat__delta today-stat__delta--neutral">${prefix}0${suffix || ''}</div>`;
    }
    const isPositive = value > 0;
    const isGood = invertColors ? !isPositive : isPositive;
    const cls = isGood ? 'today-stat__delta--up' : 'today-stat__delta--down';
    const sign = isPositive ? prefix : '';
    return `<div class="today-stat__delta ${cls}">${sign}${value}${suffix || ''}</div>`;
}

// =============================================================================
// Section: Post Suggestions
// =============================================================================

function renderPostSuggestionsSection() {
    const loadingHtml = '<div class="today-section__empty">Loading content plan...</div>';
    return renderSection('Posts', null, loadingHtml, 'Suggested posts for today');
}

// =============================================================================
// Section: Messages — grouped sub-sections per label, collapsed by default
// =============================================================================

// All items rendered per group — each group scrolls independently

// Priority order: Welcome first (greet new members), then Cooling (still saveable),
// then Silent (re-engage), then Lurker (activate), then Elsewhere (lowest priority)
const messageGroups = [
    { key: 'welcome',          label: 'Welcome',    desc: 'Newly Joined',        badgeCls: 'today-badge--welcome',    defaultExpanded: true },
    { key: 'cooling',          label: 'Cooling',    desc: 'Losing Interest',     badgeCls: 'today-badge--cooling',     defaultExpanded: true },
    { key: 'reactivate',       label: 'Silent',     desc: 'Gone Quiet',          badgeCls: 'today-badge--silent',      defaultExpanded: true },
    { key: 'lurker',           label: 'Lurker',     desc: 'Never Posted',        badgeCls: 'today-badge--lurker',      defaultExpanded: true },
    { key: 'active_elsewhere', label: 'Elsewhere',  desc: 'Active in Other Groups', badgeCls: 'today-badge--elsewhere',   defaultExpanded: true },
];

const ITEMS_PER_GROUP = 3; // Show top N items initially

function renderMessagesSection(data) {
    const dm = data.dm_candidates || {};

    // Build buckets per label (outreach types filled async by loadOutreachData)
    // Priority order: Welcome > Cooling > Silent > Lurker > Elsewhere
    // Each member appears in only one category (highest priority wins)
    const seen = new Set();
    const dedup = (items, type) => items
        .filter(m => { const id = m.skool_id; if (seen.has(id)) return false; seen.add(id); return true; })
        .map(m => ({ type, member: m }));

    const welcomeItems    = dedup(dm.welcome_dm || [], 'welcome');
    const coolingItems    = dedup(dm.cooling || [], 'cooling');
    const reactivateItems = dedup(dm.reactivate || [], 'reactivate');
    const lurkerItems     = dedup((data.lurkers || {}).members || [], 'lurker');
    const elsewhereItems  = dedup(dm.active_elsewhere || [], 'active_elsewhere');

    window._messageBuckets = {
        active_elsewhere: elsewhereItems,
        cooling:          coolingItems,
        welcome:          welcomeItems,
        reactivate:       reactivateItems,
        lurker:           lurkerItems
    };

    const totalCount = window._messageBuckets.welcome.length
        + window._messageBuckets.cooling.length
        + window._messageBuckets.reactivate.length
        + window._messageBuckets.lurker.length
        + window._messageBuckets.active_elsewhere.length;

    const html = renderMessageGroups();

    return renderSection('Messages', totalCount > 0 ? totalCount : null, html, 'People to reach out to');
}

function renderMessageGroups() {
    const buckets = window._messageBuckets || {};
    let html = '';

    for (const g of messageGroups) {
        const items = buckets[g.key] || [];
        const isEmpty = items.length === 0;

        const sorted = isEmpty ? [] : sortDismissedToBottom(items);
        const groupId = 'msg-group-' + g.key;
        const isCollapsed = !g.defaultExpanded;
        const collapsedCls = isCollapsed ? ' msg-group--collapsed' : '';
        const emptyCls = isEmpty ? ' msg-group--empty' : '';

        html += `<div class="msg-group${collapsedCls}${emptyCls}" id="${groupId}">`;
        html += `<div class="msg-group__header"${isEmpty ? '' : ` onclick="toggleMsgGroup('${g.key}')"`}>
            ${isEmpty ? '' : '<span class="msg-group__toggle">\u25BC</span>'}
            <span class="today-badge ${g.badgeCls}">${g.label}</span>
            <span class="msg-group__desc">${g.desc}</span>
            <span class="msg-group__count">${items.length}</span>
        </div>`;

        if (!isEmpty) {
            html += `<div class="msg-group__list">`;
            for (const item of sorted) {
                html += renderGroupItem(item);
            }
            html += '</div>';
        }

        html += '</div>';
    }

    return html;
}

/** Toggle collapse/expand for a message group */
function toggleMsgGroup(key) {
    const el = document.getElementById('msg-group-' + key);
    if (el) el.classList.toggle('msg-group--collapsed');
}

/** Expand hidden items in a group */
function expandGroup(key) {
    const buckets = window._messageBuckets || {};
    const items = buckets[key] || [];
    const sorted = sortDismissedToBottom(items);
    const hidden = sorted.slice(ITEMS_PER_GROUP);

    const showAllEl = document.getElementById('show-all-' + key);
    if (!showAllEl) return;

    let html = '';
    for (const item of hidden) {
        html += renderGroupItem(item);
    }
    showAllEl.outerHTML = html;
}

function renderGroupItem(item) {
    if (item.type === 'outreach') {
        return renderOutreachCard(item.touch);
    } else {
        return renderMessageItem(item.type, item.member);
    }
}

/** Sort dismissed/checked items to the bottom of the list */
function sortDismissedToBottom(items) {
    return [...items].sort((a, b) => {
        const aDismissed = a.touch ? (a.touch.dismissed_at > 0 ? 1 : 0) : 0;
        const bDismissed = b.touch ? (b.touch.dismissed_at > 0 ? 1 : 0) : 0;
        return aDismissed - bDismissed;
    });
}

/** Toggle outreach card between checked (awaiting verification) and unchecked */
function toggleOutreachCard(checkbox) {
    const card = checkbox.closest('.outreach-card');
    if (!card) return;
    const statusEl = card.querySelector('.outreach-card__status');
    const actionsEl = card.querySelector('.outreach-card__actions');

    if (checkbox.checked) {
        // Mark as done — slide to bottom, show "waiting for approval"
        card.classList.add('outreach-card--dismissed');
        if (statusEl) {
            statusEl.style.display = '';
            statusEl.className = 'outreach-card__status outreach-card__status--awaiting';
            statusEl.textContent = 'Waiting for approval — next fetch will verify';
        }
        if (actionsEl) actionsEl.style.display = 'none';
        // Move card to the bottom of its group
        const group = card.closest('.msg-group__list');
        if (group) group.appendChild(card);
    } else {
        // Undo — restore card
        card.classList.remove('outreach-card--dismissed');
        if (statusEl) statusEl.style.display = 'none';
        if (actionsEl) actionsEl.style.display = '';
    }
}

/** Skip an outreach card — same as checking it but without the checkbox */
function skipOutreachCard(btn) {
    const card = btn.closest('.outreach-card');
    if (!card) return;
    const checkbox = card.querySelector('.outreach-card__checkbox');
    if (checkbox) {
        checkbox.checked = true;
        toggleOutreachCard(checkbox);
    }
}

function renderMessageItem(type, m) {
    let ctx = '';
    let churnHtml = '';
    switch (type) {
        case 'welcome':
            ctx = `Joined ${m.joined_days_ago}d ago`;
            break;
        case 'reactivate':
            ctx = `Last activity ${m.inactive_days} days ago`;
            break;
        case 'lurker':
            ctx = `Gave ${m.likes_given} Likes since joined`;
            break;
        case 'cooling':
            ctx = `Activity dropped ${m.drop_pct}%`;
            break;
        case 'active_elsewhere': {
            const pct = m.skool_activity_7d > 0
                ? ((m.community_activity_7d / m.skool_activity_7d) * 100).toFixed(1)
                : '0.0';
            ctx = `${m.skool_activity_7d} activities on Skool · ${pct}% in your group`;
            break;
        }
    }
    if (m.churn_score > 25) {
        churnHtml = `<div class="outreach-card__churn">Churn: ${m.churn_score} (${m.churn_dominant_signal || ''})</div>`;
    }

    const displayName = m.name || m.skool_id || '?';
    const init = (displayName[0] || '?').toUpperCase();
    const skoolId = m.skool_id || '';
    const avatar = skoolId
        ? `<img class="outreach-card__avatar" src="/api/image/${skoolId}" onerror="this.outerHTML='<div class=\\'outreach-card__avatar outreach-card__avatar--placeholder\\' style=\\'background:var(--brand-primary)\\'>${init}</div>'" alt="">`
        : `<div class="outreach-card__avatar outreach-card__avatar--placeholder" style="background:var(--brand-primary)">${init}</div>`;

    const mj = JSON.stringify({name:displayName,skool_id:skoolId}).replace(/&/g,'&amp;').replace(/"/g,'&quot;');
    const actions = `<div class="outreach-card__actions">
        <button class="ck-btn ck-btn--primary ck-btn--xs acb-action-btn" onclick="lib.generateDmSuggestion(JSON.parse(this.dataset.member))" data-member="${mj}">DM Draft</button>
        <a class="ck-btn ck-btn--secondary ck-btn--xs" href="/people.html?id=${skoolId}">Profile</a>
        <button class="ck-btn ck-btn--secondary ck-btn--xs" onclick="skipOutreachCard(this)">Skip</button>
    </div>`;

    return `<div class="outreach-card" data-skool-id="${skoolId}">
        <input type="checkbox" class="outreach-card__checkbox" onchange="toggleOutreachCard(this)">
        ${avatar}
        <div class="outreach-card__content">
            <div class="outreach-card__header"><span class="outreach-card__name">${escHtml(displayName)}</span> <span class="outreach-card__touch" title="Touch 1 of ${{welcome:5,reactivate:4,lurker:3}[type]||3}">1/${{welcome:5,reactivate:4,lurker:3}[type]||3}</span></div>
            <div class="outreach-card__context">${ctx}</div>${churnHtml}${actions}
            <div class="outreach-card__status" style="display:none"></div>
        </div>
    </div>`;
}

// =============================================================================
// Shared: Section wrapper (with optional footer)
// =============================================================================

const sectionIcons = { 'Posts': '\u{1F4DD}', 'Messages': '\u{1F4AC}' };
const sectionIds = { 'Posts': 'section-post', 'Messages': 'section-messages' };

const sectionBodyClass = { 'Messages': ' today-section__body--grid', 'Posts': ' today-section__body--horizontal' };
const sectionExtraClass = { 'Posts': ' today-section--compact', 'Messages': ' today-section--fill' };

function renderSection(title, count, contentHtml, subtitle, footerHtml) {
    const icon = sectionIcons[title] || '';
    const id = sectionIds[title] || '';
    const bodyCls = sectionBodyClass[title] || '';
    const extraCls = sectionExtraClass[title] || '';
    const countCls = (count === null || count === undefined || count === 0) ? ' today-section__count--zero' : '';
    const countHtml = count !== null && count !== undefined
        ? `<span class="today-section__count${countCls}">${count}</span>` : '';
    const subtitleHtml = subtitle ? `<span class="today-section__subtitle">${subtitle}</span>` : '';
    return `
        <div class="today-section${extraCls}" id="${id}">
            <div class="today-section__header">
                <span class="today-section__icon">${icon}</span>
                <span class="today-section__title">${title}</span>
                ${subtitleHtml}
                ${countHtml}
            </div>
            <div class="today-section__body${bodyCls}">${contentHtml}</div>
            ${footerHtml || ''}
        </div>
    `;
}

// =============================================================================
// Outreach System — async loading into Messages section
// =============================================================================

async function loadOutreachData() {
    try {
        const resp = await fetch('/api/outreach/active');
        if (!resp.ok) return;
        const data = await resp.json();
        const touches = data.touches || [];
        if (touches.length === 0) return;

        // Sort outreach touches into their label buckets
        if (!window._messageBuckets) window._messageBuckets = {};
        for (const t of touches) {
            const key = t.outreach_type || 'active_elsewhere';
            // Map outreach_type to our bucket keys
            const bucketKey = (key === 'welcome' || key === 'reactivate' || key === 'lurker' || key === 'cooling' || key === 'active_elsewhere')
                ? key : 'active_elsewhere';
            if (!window._messageBuckets[bucketKey]) window._messageBuckets[bucketKey] = [];
            // Deduplicate: if this member already exists from briefing data, replace it
            const existingIdx = window._messageBuckets[bucketKey].findIndex(
                item => item.member?.skool_id === t.member_skool_id
            );
            if (existingIdx >= 0) {
                window._messageBuckets[bucketKey][existingIdx] = { type: 'outreach', touch: t };
            } else {
                // Prepend outreach items (higher priority than briefing items)
                window._messageBuckets[bucketKey].unshift({ type: 'outreach', touch: t });
            }
        }

        const msgSection = document.getElementById('section-messages');
        if (!msgSection) return;
        const body = msgSection.querySelector('.today-section__body');
        if (!body) return;

        body.innerHTML = renderMessageGroups();

        // Update total count badge
        const total = Object.values(window._messageBuckets).reduce((s, b) => s + b.length, 0);
        const countEl = msgSection.querySelector('.today-section__count');
        if (countEl) {
            countEl.textContent = total;
            countEl.classList.remove('today-section__count--zero');
        }

        // Render daily progress tracker
        renderDailyProgress(touches);
    } catch (e) { console.warn('[Outreach] Failed to load:', e); }
}

/** Render the daily progress tracker bar (only today's touches, not backlog) */
function renderDailyProgress(touches) {
    const el = document.getElementById('dailyProgress');
    if (!el) return;

    const todayStart = Math.floor(Date.now() / 86400000) * 86400;
    const todayEnd = todayStart + 86400;
    const todayTouches = touches.filter(t => t.scheduled_at >= todayStart && t.scheduled_at < todayEnd);

    const total = todayTouches.length;
    if (total === 0) { el.style.display = 'none'; return; }

    const done = todayTouches.filter(t => t.dismissed_at > 0).length;
    const pct = Math.round((done / total) * 100);
    const allDone = done >= total;

    el.style.display = 'flex';
    el.innerHTML = `
        <span class="today-daily-progress__label">Today's outreach</span>
        <div class="today-daily-progress__bar">
            <div class="today-daily-progress__fill${allDone ? ' today-daily-progress__fill--complete' : ''}" style="width:${pct}%"></div>
        </div>
        ${allDone
            ? '<span class="today-daily-progress__done">All caught up!</span>'
            : `<span class="today-daily-progress__count">${done} / ${total}</span>`
        }
    `;
}

function renderOutreachCard(t) {
    const isDismissed = t.dismissed_at > 0;
    const cls = isDismissed ? ' outreach-card--dismissed' : '';
    const chk = isDismissed ? ' checked disabled' : '';
    const touchLbl = t.auto_dm_detected && t.touch_number <= 1 ? `${t.touch_number}/${t.max_touches}*` : `${t.touch_number}/${t.max_touches}`;
    const ctx = buildOutreachCtx(t);
    const churn = t.churn_score > 25 ? `<div class="outreach-card__churn">Churn: ${t.churn_score} (${t.churn_dominant_signal})</div>` : '';
    const status = isDismissed ? '<div class="outreach-card__status outreach-card__status--awaiting">Marked done \u00B7 Awaiting verification...</div>' : '';
    const displayName = t.member_name || t.member_skool_id || '?';
    const init = (displayName[0] || '?').toUpperCase();
    const avatar = t.member_skool_id
        ? `<img class="outreach-card__avatar" src="/api/image/${t.member_skool_id}" onerror="this.outerHTML='<div class=\\'outreach-card__avatar outreach-card__avatar--placeholder\\' style=\\'background:var(--brand-primary)\\'>${init}</div>'" alt="">`
        : `<div class="outreach-card__avatar outreach-card__avatar--placeholder" style="background:var(--brand-primary)">${init}</div>`;
    let actions = '';
    if (!isDismissed) {
        const mj = JSON.stringify({name:displayName,skool_id:t.member_skool_id,outreach_type:t.outreach_type,posts_7d:t.posts_7d,comments_7d:t.comments_7d,likes_given_7d:t.likes_given_7d,posts_prior_14d:t.posts_prior_14d,comments_prior_14d:t.comments_prior_14d,likes_given_prior_14d:t.likes_given_prior_14d}).replace(/&/g,'&amp;').replace(/"/g,'&quot;');
        actions = `<div class="outreach-card__actions">
            <button class="ck-btn ck-btn--secondary ck-btn--xs acb-action-btn" onclick="lib.generateDmSuggestion(JSON.parse(this.dataset.member))" data-member="${mj}">DM Draft</button>
            <a class="ck-btn ck-btn--secondary ck-btn--xs" href="/people.html?id=${t.member_skool_id}">Profile</a>
            <button class="ck-btn ck-btn--secondary ck-btn--xs" onclick="cancelOutreachTouch(${t.id})">Skip</button>
        </div>`;
    }
    return `<div class="outreach-card${cls}" id="outreach-card-${t.id}">
        <input type="checkbox" class="outreach-card__checkbox" ${chk} onchange="dismissOutreachTouch(${t.id}, this)">
        ${avatar}
        <div class="outreach-card__content">
            <div class="outreach-card__header"><span class="outreach-card__name">${escHtml(displayName)}</span> <span class="outreach-card__touch" title="Touch ${t.touch_number} of ${t.max_touches}">${touchLbl}</span></div>
            <div class="outreach-card__context">${ctx}</div>${churn}${status}${actions}
        </div>
    </div>`;
}

function buildEngagementDropCtx(t) {
    // Weighted engagement score: posts×3 + comments×2 + likes×1
    const recent = (t.posts_7d || 0) * 3 + (t.comments_7d || 0) * 2 + (t.likes_given_7d || 0);
    const priorWeekly = ((t.posts_prior_14d || 0) * 3 + (t.comments_prior_14d || 0) * 2 + (t.likes_given_prior_14d || 0)) / 2;
    if (priorWeekly <= 0) {
        const actions7d = (t.posts_7d || 0) + (t.comments_7d || 0) + (t.likes_given_7d || 0);
        return `${actions7d} actions this week · was more active before`;
    }
    const changePct = Math.round(((recent - priorWeekly) / priorWeekly) * 100);
    const priorLabel = Math.round(priorWeekly);
    const recentLabel = Math.round(recent);
    const isUp = changePct >= 0;
    const arrow = isUp ? '▲' : '▼';
    const color = isUp ? 'var(--color-success)' : 'var(--color-danger, #e74c3c)';
    return `<span style="color:${color}">${arrow} ${Math.abs(changePct)}%</span> this week — was ${priorLabel} actions/wk, now ${recentLabel}`;
}

function buildOutreachCtx(t) {
    switch(t.outreach_type) {
        case 'welcome': return `Joined ${t.joined_days_ago}d ago`;
        case 'reactivate': return `Last activity ${t.last_active_days_ago} days ago`;
        case 'lurker': return `Gave ${t.likes_given} Likes since joined`;
        case 'cooling': return buildEngagementDropCtx(t);
        case 'active_elsewhere': {
            const skool = t.skool_activity_7d || 0;
            const community = t.community_activity_7d || 0;
            const pct = skool > 0 ? ((community / skool) * 100).toFixed(2) : '0.00';
            return `${skool} activities on Skool this week · ${pct}% in your group`;
        }
        default: return t.outreach_type;
    }
}

async function dismissOutreachTouch(id, cb) {
    const isDismissing = cb.checked;
    const endpoint = isDismissing ? 'dismiss' : 'undismiss';
    try {
        const r = await fetch(`/api/outreach/${id}/${endpoint}`, {method:'POST', headers:{'Content-Length':'0'}});
        if (!r.ok) throw new Error('HTTP ' + r.status);

        // Find and update the touch in whichever bucket it lives in
        const buckets = window._messageBuckets || {};
        let touchBucketKey = null;
        for (const [key, items] of Object.entries(buckets)) {
            const found = items.find(b => b.touch && b.touch.id === id);
            if (found) {
                found.touch.dismissed_at = isDismissing ? 1 : 0;
                touchBucketKey = key;
                break;
            }
        }

        // Re-render that group to move dismissed items to bottom
        if (touchBucketKey) {
            const groupEl = document.getElementById('msg-group-' + touchBucketKey);
            if (groupEl) {
                const listEl = groupEl.querySelector('.msg-group__list');
                if (listEl) {
                    const sorted = sortDismissedToBottom(buckets[touchBucketKey]);
                    let html = '';
                    for (const item of sorted) html += renderGroupItem(item);
                    listEl.innerHTML = html;
                }
            }
        }

        // Update daily progress tracker
        const allTouches = Object.values(buckets)
            .flat()
            .filter(b => b.type === 'outreach')
            .map(b => b.touch);
        renderDailyProgress(allTouches);
    } catch(e) { console.error('[Outreach] ' + endpoint + ' failed:', e); cb.checked = !cb.checked; }
}

async function cancelOutreachTouch(id) {
    if (!confirm('Cancel this outreach and the entire cycle?')) return;
    try {
        const r = await fetch(`/api/outreach/${id}/cancel`, {method:'POST', headers:{'Content-Length':'0'}});
        if (!r.ok) throw new Error('HTTP ' + r.status);
        const card = document.getElementById('outreach-card-' + id);
        if (card) card.remove();
    } catch(e) { console.error('[Outreach] Cancel failed:', e); }
}

// =============================================================================
// Content Plan — AI-powered daily post suggestions
// =============================================================================

function renderWeekendRecap() {
    const h = briefingData ? briefingData.headline : null;
    if (!h) return '<div class="today-section__empty">Enjoy your weekend!</div>';

    const newMembers = h.new_members_week || 0;
    const activeMembers = h.active_members_week || 0;
    const activities = h.activities_week || 0;

    // Pick an encouraging message based on activity level
    let praise;
    if (activities > 200) praise = "Your community was buzzing this week — amazing work!";
    else if (activities > 50) praise = "Solid week! Your community stayed active and engaged.";
    else if (activities > 0) praise = "Every interaction counts — you kept things moving this week.";
    else praise = "A quiet week — perfect time to recharge and plan ahead.";

    // Build stat pills — only show stats that have meaningful values
    const stats = [];
    if (newMembers > 0) stats.push(`<span class="weekend-recap__stat">+${newMembers} new member${newMembers !== 1 ? 's' : ''}</span>`);
    if (activeMembers > 0) stats.push(`<span class="weekend-recap__stat">${activeMembers} active member${activeMembers !== 1 ? 's' : ''}</span>`);
    if (activities > 0) stats.push(`<span class="weekend-recap__stat">${activities} activit${activities !== 1 ? 'ies' : 'y'}</span>`);

    const statsHtml = stats.length > 0
        ? `<div class="weekend-recap__stats">${stats.join('')}</div>`
        : '';

    return `<div class="weekend-recap">
        <div class="weekend-recap__title">Week in Review</div>
        <div class="weekend-recap__praise">${praise}</div>
        ${statsHtml}
        <div class="weekend-recap__footer">No posts scheduled for the weekend. Enjoy your time off!</div>
    </div>`;
}

async function loadContentPlan() {
    try {
        const resp = await fetch('/api/today/content-plan');
        if (!resp.ok) return;
        const data = await resp.json();
        if (data.is_weekend) {
            const postsSection = document.getElementById('section-post');
            if (postsSection) {
                const sub = postsSection.querySelector('.today-section__subtitle');
                if (sub) sub.textContent = 'Your week at a glance';
                const body = postsSection.querySelector('.today-section__body');
                if (body) body.innerHTML = renderWeekendRecap();
            }
            return;
        }

        const postsSection = document.getElementById('section-post');
        if (!postsSection) return;
        const body = postsSection.querySelector('.today-section__body');
        if (!body) return;

        let contentHtml = '';
        const communityInfo = {
            slug: data.community_slug || '',
            name: data.community_name || '',
            logoUrl: data.community_logo_url || ''
        };
        contentHtml += renderInternalPostCard(data, communityInfo, data.best_posting_hours || []);

        if (data.external && data.external.community_name) {
            contentHtml += renderExternalPostCard(data);
        }

        // Missing community hint (single daily suggestion)
        const hint = data.missing_community_hint;
        if (hint && hint.slug) {
            const joinUrl = `https://www.skool.com/${escHtml(hint.slug)}`;
            contentHtml += `<div class="missing-community-hint">Hint: ${hint.shared_members} members of your community are in <strong>${escHtml(hint.name)}</strong> which you aren't a part of. <a href="${joinUrl}" target="_blank">Join that community</a> for more outreach.</div>`;
        }


        body.innerHTML = contentHtml || '<div class="today-section__empty">No posts suggested for today.</div>';

        const countEl = postsSection.querySelector('.today-section__count');
        if (countEl) {
            let count = 1;
            if (data.external && data.external.community_name) count++;
            countEl.textContent = count;
            countEl.classList.remove('today-section__count--zero');
        }
    } catch (e) { console.warn('[ContentPlan] Failed to load:', e); }
}

function renderInternalPostCard(data, community, bestHours) {
    const badgeCls = 'content-plan-badge--' + data.post_type;
    const internal = data.internal || {};
    let bodyHtml = '';
    let membersHtml = '';

    switch (data.post_type) {
        case 'welcome': {
            const members = internal.members || [];
            if (members.length === 0) {
                bodyHtml = '<p>No new members this week — consider a theme kickoff post instead.</p>';
            } else {
                bodyHtml = `<p>${members.length} new member${members.length > 1 ? 's' : ''} to welcome this week</p>`;
                membersHtml = '<div class="content-plan-card__members">';
                for (const m of members.slice(0, 6)) {
                    membersHtml += `<span class="content-plan-card__member-pill">
                        <img src="/api/image/${m.skool_id}" onerror="this.style.display='none'" alt="">
                        ${escHtml(m.name)}
                    </span>`;
                }
                if (members.length > 6) membersHtml += `<span class="content-plan-card__member-pill">+${members.length - 6} more</span>`;
                membersHtml += '</div>';
            }
            break;
        }
        case 'spotlight': {
            const top = (internal.top_contributors || [])[0];
            const unsung = internal.unsung_heroes || [];
            if (top) {
                bodyHtml = `<p>Spotlight: <strong>${escHtml(top.name)}</strong> — ${top.posts_7d} posts, ${top.comments_7d} comments this week`;
                if (top.top_post_title) bodyHtml += ` (top: "${escHtml(top.top_post_title)}")`;
                bodyHtml += '</p>';
            }
            if (unsung.length > 0) {
                bodyHtml += `<p style="font-size:0.7rem;color:var(--color-text-disabled)">Unsung: ${unsung.map(u => escHtml(u.name)).join(', ')}</p>`;
            }
            break;
        }
        case 'engagement': {
            const topics = internal.trending_topics || [];
            const lurkerCount = internal.lurker_count || 0;
            if (topics.length > 0) {
                bodyHtml = '<p>Trending: ' + topics.slice(0, 3).map(t => `"${escHtml(t.title)}" (${t.upvotes}\u2191 ${t.comments}\u{1F4AC})`).join(', ') + '</p>';
            }
            if (lurkerCount > 0) {
                bodyHtml += `<p>${lurkerCount} lurkers — try a poll!</p>`;
            }
            const interests = internal.interests || [];
            if (interests.length > 0) {
                membersHtml = '<div class="content-plan-card__members">';
                for (const i of interests.slice(0, 5)) {
                    membersHtml += `<span class="content-plan-interest-tag">${escHtml(i.label)}</span>`;
                }
                membersHtml += '</div>';
            }
            break;
        }
        case 'challenge': {
            break;
        }
        case 'humor': {
            const milestone = internal.nearest_milestone || 0;
            if (milestone > 0) bodyHtml = `<p>Near milestone: <strong>${milestone} members</strong></p>`;
            break;
        }
    }

    // Voice profile indicator (auto-generated in background)
    const vp = data.voice_profile || {};
    let voiceHtml = '';
    if (vp.has_profile) {
        voiceHtml = `<span class="content-plan-voice-indicator content-plan-voice-indicator--active" title="AI drafts will match your writing style">Voice matched</span>`;
    } else if (vp.reason === 'insufficient_posts') {
        voiceHtml = `<span class="content-plan-voice-indicator" title="Need ${5 - (vp.post_count || 0)} more posts to learn your writing style">Learning your voice...</span>`;
    }
    // If not_generated but enough posts: auto-generation was triggered server-side, will appear on next load

    const contextJson = JSON.stringify({
        post_type: data.post_type, post_type_label: data.post_type_label,
        internal: data.internal, language: data.language,
        voice_profile: data.voice_profile, stats: data.stats
    }).replace(/&/g, '&amp;').replace(/"/g, '&quot;');

    const logoHtml = community && community.logoUrl
        ? `<img class="content-plan-card__logo" src="${escHtml(community.logoUrl)}" alt="" onerror="this.style.display='none'">`
        : '';
    const communityName = community && community.name ? escHtml(community.name) : '';
    const postHereUrl = community && community.slug
        ? `https://www.skool.com/${escHtml(community.slug)}`
        : '#';

    const postTypeDescs = {
        welcome: 'Welcome new members and kick off the week with a theme.',
        spotlight: 'Highlight an active member to boost recognition.',
        engagement: 'Ask a question or run a poll to spark conversation.',
        challenge: 'Post a challenge or share a behind-the-scenes moment.',
        humor: 'Keep it light with humor or casual smalltalk.'
    };
    const descText = postTypeDescs[data.post_type] || '';

    // Best posting time (first hour from engagement-weighted analysis)
    let postTimeHtml = '';
    if (bestHours && bestHours.length > 0) {
        const h = bestHours[0];
        const ampm = h >= 12 ? 'pm' : 'am';
        const h12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
        postTimeHtml = ` <span class="content-plan-card__post-time">— Post this at: ${h12}:00 ${ampm}</span>`;
    }

    return `<div class="content-plan-card">
        <div class="content-plan-card__community">
            ${logoHtml}
            <span class="content-plan-card__community-name">${communityName}</span>
        </div>
        <div class="content-plan-card__info">
            <div class="content-plan-card__header">
                <span class="content-plan-badge ${badgeCls}">${escHtml(data.post_type)}</span>
            </div>
            <div class="content-plan-card__desc">${escHtml(descText)}${postTimeHtml}</div>
        </div>
        <div class="content-plan-card__actions">
            <button class="ck-btn ck-btn--primary ck-btn--xs acb-action-btn" onclick="lib.generateInternalPostDraft(JSON.parse(this.dataset.ctx))" data-ctx="${contextJson}">Generate Draft</button>
            <a class="ck-btn ck-btn--secondary ck-btn--xs" href="${postHereUrl}" target="_blank">Post here</a>
        </div>
    </div>`;
}

function renderExternalPostCard(data) {
    const ext = data.external;
    const interests = ext.shared_interests || [];

    let interestTags = '';
    if (interests.length > 0) {
        interestTags = '<div class="content-plan-card__members" style="margin-top:var(--space-1)">';
        for (const tag of interests.slice(0, 4)) {
            interestTags += `<span class="content-plan-interest-tag">${escHtml(tag)}</span>`;
        }
        interestTags += '</div>';
    }

    const contextJson = JSON.stringify({
        community_name: ext.community_name, community_slug: ext.community_slug,
        about_summary: ext.about_summary, shared_interests: ext.shared_interests,
        language: data.language, voice_profile: data.voice_profile
    }).replace(/&/g, '&amp;').replace(/"/g, '&quot;');

    const extLogoHtml = ext.community_logo_url
        ? `<img class="content-plan-card__logo" src="${escHtml(ext.community_logo_url)}" alt="" onerror="this.style.display='none'">`
        : '';
    const extPostUrl = ext.community_slug
        ? `https://www.skool.com/${escHtml(ext.community_slug)}`
        : '#';

    return `<div class="content-plan-external">
        <div class="content-plan-card__community">
            ${extLogoHtml}
            <span class="content-plan-card__community-name">${escHtml(ext.community_name)}</span>
        </div>
        <div class="content-plan-card__info">
            <div class="content-plan-external__header">
                <span class="content-plan-badge content-plan-badge--engagement">External</span>
                <span class="content-plan-voice-indicator">${ext.shared_member_count} shared members</span>
            </div>
            <div class="content-plan-card__desc">Cross-post to engage shared members in this community.</div>
        </div>
        <div class="content-plan-card__actions">
            <button class="ck-btn ck-btn--primary ck-btn--xs acb-action-btn" onclick="lib.generateExternalPostDraft(JSON.parse(this.dataset.ctx))" data-ctx="${contextJson}">Generate Draft</button>
            <a class="ck-btn ck-btn--secondary ck-btn--xs" href="${extPostUrl}" target="_blank">Post here</a>
        </div>
    </div>`;
}

function extractDescription(aboutSummary) {
    if (!aboutSummary) return '';
    try {
        const parsed = JSON.parse(aboutSummary);
        // Try multiple known Skool about_data structures
        const desc = parsed?.pageProps?.settings?.pageMeta?.description
            || parsed?.pageProps?.currentGroup?.metadata?.description
            || parsed?.description
            || '';
        // If we parsed JSON but found no description, return empty rather than raw JSON
        return desc;
    } catch {
        // Not JSON — return as plain text only if it doesn't look like JSON
        if (aboutSummary.trimStart().startsWith('{') || aboutSummary.trimStart().startsWith('[')) return '';
        return aboutSummary;
    }
}

// =============================================================================
// Utility
// =============================================================================

function escHtml(s) {
    return lib.escapeHtml ? lib.escapeHtml(s || '') : (s || '').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}

// =============================================================================
// Page Walkthrough — Home
// =============================================================================

if (typeof Walkthrough !== 'undefined') {
    Walkthrough.registerPage('home', [
        {
            target: null,
            title: 'Welcome to catknows!',
            body: "This is your daily briefing \u2014 everything you need to know about your community today, in one place. Let's walk through it."
        },
        {
            target: '#section-post',
            title: 'Your Daily Tasks',
            body: 'catknows suggests what to post each day and who to reach out to. Hit "Generate Draft" to let AI write it, or work through the people list below.'
        },
        {
            target: '#section-messages',
            title: 'People to Reach Out To',
            body: 'Members grouped by priority: welcome new joiners, re-engage cooling members, and activate lurkers. Click any name to open their profile.'
        },
        {
            target: '.ck-navbar__links',
            title: 'Explore Further',
            body: 'When you\'re ready to dig deeper, use the top bar: People for members, Conversations for posts and messages, Discover for network or activity graphs, and Insights for analytics.'
        }
    ]);
}
