import { apiGet } from '../api.js';
import { pageHeaderHTML, showToast } from '../app.js';

const FETCH_LIMIT = 100;
const CLIENT_GROUP_PAGE = 10;
const UPLOADS_VISIBLE = 5;

let coachesList = [];
let expandedCoachId = null;
/** @type {Record<string, { submissions: object[], total: number }>} */
let recentByCoach = {};
/** @type {Record<string, { clientLimit: number, expandedClients: Set<string>, showAllUploads: Set<string>, filter: string }>} */
let coachDetailUi = {};
let filterSearch = '';

export async function coachesPage() {
    const app = document.getElementById('app');
    app.innerHTML = `
        ${pageHeaderHTML('Counselor activity')}
        <div id="coachesContent"><div class="spinner"></div></div>
    `;

    try {
        const data = await apiGet('coaches.php');
        coachesList = data.coaches || [];
        renderCoaches();
    } catch (e) {
        showToast(e.message, 'error');
        document.getElementById('coachesContent').innerHTML =
            `<p class="error-text">${esc(e.message)}</p>`;
    }
}

function coachSearchText(c) {
    return [c.username, c.coachID, c.supervisorUsername].filter(Boolean).join(' ');
}

function coachHasUploads(c) {
    return (c.totalSubmissions ?? 0) > 0;
}

function filteredCoaches() {
    const q = filterSearch.trim().toLowerCase();
    if (!q) return coachesList;
    return coachesList.filter(c => coachSearchText(c).toLowerCase().includes(q));
}

function getCoachUi(coachID) {
    if (!coachDetailUi[coachID]) {
        coachDetailUi[coachID] = {
            clientLimit: CLIENT_GROUP_PAGE,
            expandedClients: new Set(),
            showAllUploads: new Set(),
            filter: '',
        };
    }
    return coachDetailUi[coachID];
}

function groupSubmissionsByClient(submissions) {
    const map = new Map();
    for (const s of submissions) {
        const code = s.clientCode || '';
        if (!map.has(code)) {
            map.set(code, []);
        }
        map.get(code).push(s);
    }
    const groups = [];
    for (const [clientCode, uploads] of map) {
        uploads.sort((a, b) => String(b.submittedAt).localeCompare(String(a.submittedAt)));
        groups.push({
            clientCode,
            uploads,
            count: uploads.length,
            lastAt: uploads[0]?.submittedAt || '',
        });
    }
    groups.sort((a, b) => String(b.lastAt).localeCompare(String(a.lastAt)));
    return groups;
}

function filterClientGroups(groups, q) {
    if (!q) return groups;
    const needle = q.toLowerCase();
    return groups.filter(g => {
        if (g.clientCode.toLowerCase().includes(needle)) return true;
        return g.uploads.some(u =>
            (u.questionnaireName || '').toLowerCase().includes(needle)
            || (u.questionnaireID || '').toLowerCase().includes(needle)
        );
    });
}

function uploadsTableHTML(uploads) {
    if (!uploads.length) {
        return '<p class="data-toolbar-hint">No uploads</p>';
    }
    return `
        <table class="data-table data-table-compact">
            <thead>
                <tr><th>When</th><th>Questionnaire</th><th>Ver.</th></tr>
            </thead>
            <tbody>
                ${uploads.map(s => `
                    <tr>
                        <td>${esc(s.submittedAt)}</td>
                        <td>${esc(s.questionnaireName)}</td>
                        <td>${s.version}</td>
                    </tr>
                `).join('')}
            </tbody>
        </table>`;
}

function coachRecentPanelHTML(coachID) {
    const data = recentByCoach[coachID];
    if (!data) {
        return '<p class="data-toolbar-hint">Loading…</p>';
    }
    const ui = getCoachUi(coachID);
    const allGroups = groupSubmissionsByClient(data.submissions || []);
    const groups = filterClientGroups(allGroups, ui.filter.trim());
    const visibleGroups = groups.slice(0, ui.clientLimit);
    const hasMoreClients = groups.length > ui.clientLimit;
    const hasMoreUploads = (data.submissions?.length ?? 0) < (data.total ?? 0);

    const summary = data.total
        ? `${data.total} upload${data.total === 1 ? '' : 's'} · ${allGroups.length} client${allGroups.length === 1 ? '' : 's'}`
        : 'No uploads';

    let groupsHTML = '';
    if (!groups.length) {
        groupsHTML = `<p class="data-toolbar-hint">${ui.filter.trim() ? 'No matches' : 'No uploads'}</p>`;
    } else {
        groupsHTML = visibleGroups.map(g => {
            const expanded = ui.expandedClients.has(g.clientCode);
            const showAll = ui.showAllUploads.has(g.clientCode);
            const visibleUploads = showAll ? g.uploads : g.uploads.slice(0, UPLOADS_VISIBLE);
            const hiddenCount = g.uploads.length - UPLOADS_VISIBLE;
            return `
                <div class="coach-client-group" data-client="${esc(g.clientCode)}">
                    <button type="button" class="coach-client-toggle btn btn-sm btn-link"
                        data-coach="${esc(coachID)}" data-client="${esc(g.clientCode)}">
                        ${expanded ? '▼' : '▶'}
                        <code>${esc(g.clientCode)}</code>
                        <span class="coach-client-meta">${g.count} upload${g.count === 1 ? '' : 's'} · last ${esc(g.lastAt || '—')}</span>
                    </button>
                    ${expanded ? `
                        <div class="coach-client-uploads">
                            ${uploadsTableHTML(visibleUploads)}
                            ${!showAll && hiddenCount > 0 ? `
                                <button type="button" class="btn btn-sm coach-show-all-uploads"
                                    data-coach="${esc(coachID)}" data-client="${esc(g.clientCode)}">
                                    Show all ${g.count} uploads
                                </button>
                            ` : ''}
                        </div>
                    ` : ''}
                </div>`;
        }).join('');
    }

    return `
        <div class="coach-recent-panel coach-recent-scroll" data-coach-panel="${esc(coachID)}">
            <div class="coach-recent-toolbar">
                <input type="search" class="filter-search coach-detail-search"
                    placeholder="Filter client or questionnaire…"
                    value="${esc(ui.filter)}"
                    data-coach="${esc(coachID)}">
                <span class="data-toolbar-hint">${esc(summary)}${ui.filter.trim() && groups.length !== allGroups.length
        ? ` · ${groups.length} shown`
        : ''}</span>
            </div>
            <div class="coach-client-groups">${groupsHTML}</div>
            <div class="coach-recent-actions">
                ${hasMoreClients ? `
                    <button type="button" class="btn btn-sm coach-more-clients" data-coach="${esc(coachID)}">
                        Show more clients (${groups.length - ui.clientLimit} remaining)
                    </button>
                ` : ''}
                ${hasMoreUploads ? `
                    <button type="button" class="btn btn-sm coach-more-uploads" data-coach="${esc(coachID)}">
                        Load more uploads (${(data.total ?? 0) - (data.submissions?.length ?? 0)} remaining)
                    </button>
                ` : ''}
            </div>
        </div>`;
}

function renderCoaches() {
    const el = document.getElementById('coachesContent');

    if (!coachesList.length) {
        el.innerHTML = `<div class="card empty-state"><h3>No counselors</h3></div>`;
        return;
    }

    el.innerHTML = `
        <div class="card">
            <p class="data-toolbar-hint" style="margin:0 0 12px">
                Track uploads and client load per counselor. Expand a row to browse uploads by client.
            </p>
            <div class="filter-bar">
                <input type="search" id="coachListSearch" class="filter-search"
                    placeholder="Search counselor or supervisor…" value="${esc(filterSearch)}">
                <span class="data-toolbar-hint" id="coachListCount"></span>
            </div>
            <div class="table-wrapper">
                <table class="data-table">
                    <thead>
                        <tr>
                            <th>Counselor</th><th>Supervisor</th><th>Clients</th>
                            <th>Total uploads</th><th>7d</th><th>30d</th><th>Last upload</th>
                        </tr>
                    </thead>
                    <tbody id="coachTableBody"></tbody>
                </table>
            </div>
        </div>
    `;

    document.getElementById('coachListSearch').addEventListener('input', (e) => {
        filterSearch = e.target.value;
        const filtered = filteredCoaches();
        if (
            expandedCoachId &&
            !filtered.some(c => c.coachID === expandedCoachId && coachHasUploads(c))
        ) {
            expandedCoachId = null;
        }
        renderCoachTableBody();
    });

    renderCoachTableBody();
}

function coachRowHTML(c) {
    const canExpand = coachHasUploads(c);
    const expanded = canExpand && expandedCoachId === c.coachID;
    const expandControl = canExpand
        ? `<button type="button" class="btn btn-sm btn-link coach-expand-btn" data-coach="${esc(c.coachID)}">${expanded ? '▼' : '▶'}</button> `
        : '';
    return `
        <tr class="coach-row" data-coach="${esc(c.coachID)}">
            <td>${expandControl}<strong>${esc(c.username)}</strong></td>
            <td>${esc(c.supervisorUsername || '—')}</td>
            <td>${c.clientCount ?? 0}</td>
            <td>${c.totalSubmissions ?? 0}</td>
            <td>${c.submissionsLast7d ?? 0}</td>
            <td>${c.submissionsLast30d ?? 0}</td>
            <td>${esc(c.lastSubmissionAt || '—')}</td>
        </tr>
        ${expanded ? `
        <tr class="coach-detail-row">
            <td colspan="7">${coachRecentPanelHTML(c.coachID)}</td>
        </tr>` : ''}`;
}

function wireCoachDetailPanel(coachID) {
    const panel = document.querySelector(`[data-coach-panel="${CSS.escape(coachID)}"]`);
    if (!panel) return;

    panel.querySelector('.coach-detail-search')?.addEventListener('input', (e) => {
        getCoachUi(coachID).filter = e.target.value;
        getCoachUi(coachID).clientLimit = CLIENT_GROUP_PAGE;
        renderCoachTableBody();
    });

    panel.querySelectorAll('.coach-client-toggle').forEach(btn => {
        btn.addEventListener('click', () => {
            const ui = getCoachUi(coachID);
            const client = btn.dataset.client;
            if (ui.expandedClients.has(client)) {
                ui.expandedClients.delete(client);
            } else {
                ui.expandedClients.add(client);
            }
            renderCoachTableBody();
        });
    });

    panel.querySelectorAll('.coach-show-all-uploads').forEach(btn => {
        btn.addEventListener('click', () => {
            getCoachUi(coachID).showAllUploads.add(btn.dataset.client);
            renderCoachTableBody();
        });
    });

    panel.querySelector('.coach-more-clients')?.addEventListener('click', () => {
        getCoachUi(coachID).clientLimit += CLIENT_GROUP_PAGE;
        renderCoachTableBody();
    });

    panel.querySelector('.coach-more-uploads')?.addEventListener('click', () => {
        loadMoreCoachUploads(coachID);
    });
}

function renderCoachTableBody() {
    const body = document.getElementById('coachTableBody');
    const countEl = document.getElementById('coachListCount');
    if (!body) return;

    const filtered = filteredCoaches();

    if (!filtered.length) {
        body.innerHTML = `
            <tr>
                <td colspan="7" style="text-align:center;color:var(--text-secondary);padding:24px">
                    No counselors match
                </td>
            </tr>`;
        if (countEl) {
            countEl.textContent = filterSearch.trim()
                ? `0 of ${coachesList.length} counselors`
                : '';
        }
        return;
    }

    body.innerHTML = filtered.map(c => coachRowHTML(c)).join('');

    if (countEl) {
        const q = filterSearch.trim();
        countEl.textContent = q
            ? `${filtered.length} of ${coachesList.length} counselors`
            : `${coachesList.length} counselors${coachesList.length === 1 ? '' : ''}`;
    }

    body.querySelectorAll('.coach-expand-btn').forEach(btn => {
        btn.addEventListener('click', () => toggleCoach(btn.dataset.coach));
    });

    if (expandedCoachId) {
        wireCoachDetailPanel(expandedCoachId);
    }
}

async function fetchCoachRecent(coachID, offset = 0, append = false) {
    const data = await apiGet(
        `coaches.php?coachID=${encodeURIComponent(coachID)}&recent=1`
        + `&limit=${FETCH_LIMIT}&offset=${offset}`
    );
    const submissions = data.submissions || [];
    if (append && recentByCoach[coachID]) {
        const existing = recentByCoach[coachID].submissions || [];
        const seen = new Set(existing.map(s => s.submissionID));
        for (const s of submissions) {
            if (!seen.has(s.submissionID)) {
                existing.push(s);
            }
        }
        recentByCoach[coachID] = {
            submissions: existing,
            total: data.total ?? existing.length,
        };
    } else {
        recentByCoach[coachID] = {
            submissions,
            total: data.total ?? submissions.length,
        };
    }
}

async function loadMoreCoachUploads(coachID) {
    const data = recentByCoach[coachID];
    if (!data) return;
    const btn = document.querySelector(
        `[data-coach-panel="${CSS.escape(coachID)}"] .coach-more-uploads`
    );
    if (btn) {
        btn.disabled = true;
        btn.textContent = 'Loading…';
    }
    try {
        await fetchCoachRecent(coachID, data.submissions.length, true);
        renderCoachTableBody();
    } catch (e) {
        showToast(e.message, 'error');
        if (btn) {
            btn.disabled = false;
            btn.textContent = 'Load more uploads';
        }
    }
}

async function toggleCoach(coachID) {
    const coach = coachesList.find(c => c.coachID === coachID);
    if (!coach || !coachHasUploads(coach)) {
        return;
    }
    if (expandedCoachId === coachID) {
        expandedCoachId = null;
        renderCoachTableBody();
        return;
    }
    expandedCoachId = coachID;
    if (!coachDetailUi[coachID]) {
        coachDetailUi[coachID] = {
            clientLimit: CLIENT_GROUP_PAGE,
            expandedClients: new Set(),
            showAllUploads: new Set(),
            filter: '',
        };
    }
    renderCoachTableBody();
    if (!recentByCoach[coachID]) {
        try {
            await fetchCoachRecent(coachID, 0, false);
        } catch (e) {
            showToast(e.message, 'error');
            recentByCoach[coachID] = { submissions: [], total: 0 };
        }
        renderCoachTableBody();
    }
}

function esc(s) {
    const d = document.createElement('div');
    d.textContent = s ?? '';
    return d.innerHTML;
}
